package com.broada.apm.logic.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.broada.apm.base.BaseLogic;
import com.broada.apm.entity.SystemInfo;
import com.broada.apm.logic.SystemLogic;
import com.broada.apm.util.LicUtils;
import com.broada.apm.util.SystemManager;
import com.broada.apm.utils.ConfigureProperties;

public class SystemLogicImpl extends BaseLogic implements SystemLogic {
	private static Logger log = LoggerFactory.getLogger(SystemLogicImpl.class);
	private static Map<String, Date> dateMap = new HashMap<String, Date>();;
	private static Map<String, MonInterData> dataMap = new HashMap<String, MonInterData>();

	@Override
	public SystemInfo querySystemInfo() {
		// String str =
		// "{\"hostname\":\"25e44ad64c52\", \"disks\":{\"sys\":{\"total\":2.1, \"used\":1.1}, \"data\":{\"total\":3.1, \"used\":2.1}}, \"mem\":{\"MemTotal\":2.1, \"MemFree\":1.1, \"Buffers\":1.1, \"Cached\":1.1, \"used\":1.1}, \"sys\":{\"avgload\":0.06}, \"dns\":[\"10.0.2.3\",\"10.0.2.4\"], \"ips\":[{\"ip\":\"172.17.0.2\", \"if\":\"eth0\", \"mask\":\"255.255.0.0\", \"gateway\":\"172.17.42.1\"}], \"netflow\":{\"eth0\":{\"rxbytes\":2.1, \"rxpackages\":2.1, \"txbytes\":5.1, \"txpackage\":5.1}, \"lo\":{\"rxbytes\":3.1, \"rxpackages\":5.1, \"txbytes\":3.1, \"txpackage\":5.1}}}";

		SystemInfo systemInfo = new SystemInfo();
		/**
		 * lic信息单独捕获异常处理
		 */
		String licInfo = null;
		try {
			licInfo = LicUtils.getLicinfo();
		} catch (Exception e) {
			licInfo = "获取license信息异常";
		}
		try {
			// Map<String, Object> map = JsonUtil.json2map(str);
			Map map = SystemManager.SystemInfo();

			SystemInfo.APM apm = systemInfo.new APM();
			String version = ConfigureProperties.getString("apm.version","APM 应用性能管理系统2.0.R1");
			apm.setVersion(version);
			apm.setLicenseInfo(licInfo);

			SystemInfo.OSInfo osInfo = systemInfo.new OSInfo();
			osInfo.setHostName((String) map.get("hostname"));
			SystemInfo.OSInfo.Processor processor = osInfo.new Processor();
			Map sys = (Map) map.get("sys");
			if (sys != null) {
				String processormhz = (String) map.get("processormhz");
				double promhz = ((int) (Double.parseDouble(processormhz) / 1000 * 100)) / 100.0;
				processor.setInfo(promhz + "GHz * " + (String) map.get("processorsize"));
				processor.setAvgload((Double) (sys).get("avgload"));
			}
			osInfo.setProcessor(processor);
			SystemInfo.OSInfo.Memory memory = osInfo.new Memory();
			Map mem = (Map) map.get("mem");
			if (mem != null) {
				memory.setTotal((Double) (mem).get("MemTotal"));
				memory.setUsed((Double) (mem).get("MemTotal") * (Double) (mem).get("used"));
				memory.setUsage((Double) (mem).get("used"));
			}
			osInfo.setMemory(memory);
			SystemInfo.OSInfo.Disk systemDisk = osInfo.new Disk();
			SystemInfo.OSInfo.Disk dataDisk = osInfo.new Disk();
			Map disk = (Map) map.get("disks");
			if (disk != null) {
				Map disksys = (Map) (disk).get("sys");
				if (disksys != null) {
					double sysTotal = (Double) ((disksys).get("total") == null ? 0.0 : disksys.get("total"));
					double sysUsed = (Double) (disksys.get("used") == null ? 0.0 : disksys.get("used"));
					systemDisk.setTotal(sysTotal);
					systemDisk.setUsed(sysUsed);
					if (sysUsed > 0.0)
						systemDisk.setUsage(new BigDecimal(sysUsed / sysTotal).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
				}

				Map diskdata = (Map) (disk).get("data");
				if (diskdata != null) {
					double dataTotal = (Double) (diskdata.get("total") == null ? 0.0 : diskdata.get("total"));
					double dataUsed = (Double) (diskdata.get("used") == null ? 0.0 : diskdata.get("used"));
					dataDisk.setTotal(dataTotal);
					dataDisk.setUsed(dataUsed);
					if (dataUsed > 0.0)
						dataDisk.setUsage(new BigDecimal(dataTotal / dataUsed).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
				}
			}
			osInfo.setSystemDisk(systemDisk);
			osInfo.setDataDisk(dataDisk);

			SystemInfo.Network network = systemInfo.new Network();
			SystemInfo.Network.ManagerInterface managerInterface = network.new ManagerInterface();
			Map manaInter = (Map) ((List) map.get("ips")).get(0); // {ip=192.168.0.66, if=scope, mask=255.255.255.0, gateway=192.168.0.1}

			String networkIf = ConfigureProperties.getString("network.if");
			managerInterface.setName(networkIf==null?"eth4":networkIf);// eth0
			managerInterface.setIp((String) manaInter.get("ip"));
			managerInterface.setNetmask((String) manaInter.get("mask"));
			managerInterface.setGateway((String) manaInter.get("gateway"));
			String dnsListStr = ((List) map.get("dns")).toString();
			managerInterface.setDns(dnsListStr.substring(1, dnsListStr.length() - 1));

			network.setManagerInterface(managerInterface);
			LinkedHashMap<String, Map> netfolw = (LinkedHashMap<String, Map>) map.get("netflow");

			List<SystemInfo.Network.MonitorInterface> monitorInterfaces = new ArrayList<>();
			Map monitor = null;
			if (netfolw.keySet().contains("bond0")) {
				monitor = netfolw.get("bond0");

			} else {
				monitor = netfolw.get("eth1");
			}
			if (monitor != null) {
				SystemInfo.Network.MonitorInterface monitorInterface = network.new MonitorInterface();

				Double rxpackages = (Double) monitor.get("rxpackages");
				Double rxbytes = (Double) monitor.get("rxbytes");

				monitorInterface = initMonitorInterface(monitorInterface, "bond0", rxpackages, rxbytes);
				monitorInterfaces.add(monitorInterface);
			}

			// Iterator inter = netfolw.entrySet().iterator();
			// List<SystemInfo.Network.MonitorInterface> monitorInterfaces = new
			// ArrayList<>();
			// while(inter.hasNext()) {
			// Map.Entry entry = (Map.Entry)inter.next();
			// if("eth0".equals((String)entry.getKey()))
			// continue;
			// SystemInfo.Network.MonitorInterface monitorInterface = network.new
			// MonitorInterface();
			//
			// Double rxpackages = (Double) ((Map)entry.getValue()).get("rxpackages");
			// Double rxbytes = (Double) ((Map)entry.getValue()).get("rxbytes");
			//
			// monitorInterface = initMonitorInterface(monitorInterface,
			// (String)entry.getKey(), rxpackages, rxbytes);
			// monitorInterfaces.add(monitorInterface);
			// }
			network.setMonitorInterfaces(monitorInterfaces);

			SystemInfo.SystemTime systemTime = systemInfo.new SystemTime();
			systemTime.setTime(new Date());
			systemTime.setSyncServer(SystemManager.getSystemTimeSyncServer());
			systemTime.setStatus(SystemManager.getSystemTimeStatus());

			systemInfo.setApm(apm);
			systemInfo.setOsInfo(osInfo);
			systemInfo.setNetwork(network);
			systemInfo.setSystemTime(systemTime);

			return systemInfo;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	private SystemInfo.Network.MonitorInterface initMonitorInterface(
			com.broada.apm.entity.SystemInfo.Network.MonitorInterface monitorInterface, String name, Double rxpackages,
			Double rxbytes) {
		monitorInterface.setName(name);
		monitorInterface.setRxPackage(rxpackages.longValue());
		monitorInterface.setRxByte(rxbytes.longValue());
		if (dateMap.get(name) == null) {
			dateMap.put(name, new Date());
			MonInterData mid = new MonInterData(rxpackages, rxbytes);
			dataMap.put(name, mid);
		} else {
			Date nowDate = new Date();
			long dateDev = nowDate.getTime() - dateMap.get(name).getTime();
			MonInterData oldData = dataMap.get(name);

			BigDecimal oldPackage = new BigDecimal(oldData.getRxpackages());
			double packageDev = (new BigDecimal(rxpackages).subtract(oldPackage)).doubleValue();
			if (packageDev < 0.0)
				return monitorInterface;
			double rxPackageRate = new BigDecimal(packageDev).divide(new BigDecimal(dateDev), 3,
					BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(60000)).doubleValue();
			monitorInterface.setRxPackageRate(rxPackageRate);

			BigDecimal oldByte = new BigDecimal(oldData.getRxbytes());
			double byteDev = (new BigDecimal(rxbytes).subtract(oldByte)).doubleValue();
			if (byteDev < 0.0)
				return monitorInterface;
			double byteRate = new BigDecimal(byteDev).divide(new BigDecimal(dateDev), 3,
					BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(60000)).doubleValue();
			monitorInterface.setRxByteRate(byteRate);

			if (dateDev > 60 * 1000) {
				dateMap.put(name, nowDate);
				MonInterData newData = new MonInterData(rxpackages, rxbytes);
				dataMap.put(name, newData);
			}
		}
		return monitorInterface;
	}

	private class MonInterData {
		private double rxpackages;
		private double rxbytes;

		public MonInterData() {
			super();
		}

		public MonInterData(double rxpackages, double rxbytes) {
			super();
			this.rxpackages = rxpackages;
			this.rxbytes = rxbytes;
		}

		public double getRxpackages() {
			return rxpackages;
		}

		public void setRxpackages(double rxpackages) {
			this.rxpackages = rxpackages;
		}

		public double getRxbytes() {
			return rxbytes;
		}

		public void setRxbytes(double rxbytes) {
			this.rxbytes = rxbytes;
		}
	}
}
